package designpatterns.creation;

/**
 * 建造者模式
 * 将一个复杂的对象分解为多个简单的对象，然后一步一步构建而成
 * 分为创建者（一般配合工厂模式）和构建者
 * 使用场景：创建的对象较复杂，由多个部件构成，各部件面临着复杂的变化，但构件间的建造顺序是稳定的
 * 优点：各个具体的建造者相互独立，有利于系统的扩展。
 * 客户端不必知道产品内部组成的细节，便于控制细节风险。
 * 缺点：产品的组成部分必须相同，这限制了其使用范围。
 * 如果产品的内部变化复杂，该模式会增加很多的建造者类。
 *
 * @author jack.wu
 * @since 2019/9/19
 */
public class BuilderTest {

    public static void main(String[] args) {
        HuWeiPhoneDirector director = new HuWeiPhoneDirector();
        Phone phone = director.directPhone();
        System.out.println(phone);
    }

}

class Phone {
    /**
     * 屏幕
     */
    private Screen screen;
    /**
     * 相机
     */
    private Camera camera;
    /**
     * 处理器
     */
    private Cpu cpu;

    public Screen getScreen() {
        return screen;
    }

    public void setScreen(Screen screen) {
        this.screen = screen;
    }

    public Camera getCamera() {
        return camera;
    }

    public void setCamera(Camera camera) {
        this.camera = camera;
    }

    public Cpu getCpu() {
        return cpu;
    }

    public void setCpu(Cpu cpu) {
        this.cpu = cpu;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "screen=" + screen +
                ", camera=" + camera +
                ", cpu=" + cpu +
                '}';
    }
}

class Screen {
    private String name;
    private Double price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Screen{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

class Camera {
    private String name;
    private Double price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Camera{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

class Cpu {

    private String name;
    private Double price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Cpu{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

/**
 * 抽象构建者
 */
interface PhoneBuilder {
    /**
     * 建筑屏幕
     *
     * @return 屏幕
     */
    Screen builderScreen();

    /**
     * 建筑相机
     *
     * @return 相机
     */
    Camera builderCamera();

    /**
     * 建造处理器
     *
     * @return 处理器
     */
    Cpu builderCpu();
}

class HuWeiPhoneBuilder implements PhoneBuilder {

    @Override
    public Screen builderScreen() {
        Screen screen = new Screen();
        screen.setName("3K高清屏幕");
        screen.setPrice(888.00D);
        return screen;
    }

    @Override
    public Camera builderCamera() {
        Camera camera = new Camera();
        camera.setName("索尼相机");
        camera.setPrice(999.00D);
        return camera;
    }

    @Override
    public Cpu builderCpu() {
        Cpu cpu = new Cpu();
        cpu.setName("麒麟980");
        cpu.setPrice(1333.00D);
        return cpu;
    }

}

/**
 * 抽象手机构建者
 */
interface PhoneDirector {

    /**
     * 组装手机
     *
     * @return 手机
     */
    Phone directPhone();
}

/**
 * 具体手机构建者
 */
class HuWeiPhoneDirector implements PhoneDirector {

    @Override
    public Phone directPhone() {
        Phone phone = new Phone();
        HuWeiPhoneBuilder builder = new HuWeiPhoneBuilder();
        phone.setScreen(builder.builderScreen());
        phone.setCamera(builder.builderCamera());
        phone.setCpu(builder.builderCpu());
        return phone;
    }
}


